/** ***********************************************************************************
* @file         mcu_task.c
* @brief        MCU通信数据管理任务
* @details      主要是用来处理MCU与CPU之间的串口通信协议处理，以及接口输出。
* @author       杨小珛
* @date         2020/12/24
* @copyright    北京高知科技有限公司    
* @version      V1.0
* @attention    无
**************************************************************************************/
#include "mcu_task.h"
#include "mon_task.h"
#include "log_task.h"
#include "power_task.h"
#include "com_lib.h"
#include "flash_buffer.h"
#include "flash_config.h"

GaozMutexHandle_t mcu_rev_data_mutex;       
GaozMutexHandle_t mcu_uart_driver_mutex;    /*数据发送互斥体*/
GaozQueueHandle_t mcu_recv_data_queue;      /*定义网络发送数据消息队列*/
GaozQueueHandle_t mcu_can_cfg_data_queue;      /*定义CAN CFG数据消息队列*/
GaozSemaphoreHandle_t mcu_can_cfg_semaphore;

mcu_uart_driver_callback_t mcu_uart_driver_cb;
mcu_uart_state_callback_t mcu_uart_state_cb;

volatile uint8_t mcu_power_man_id;          /*MCU管理ID*/
volatile uint32_t mcu_can_cfg_sem_reg;  
GaozMutexHandle_t mcu_can_cfg_mutex;      
mcu_can_cfg_para_t mcu_can_cfg_unit_para[UNIT_CONTROL_CONFIG_INDEX]; 
mcu_can_cfg_para_t mcu_can_cfg_dtc_para[DTC_CONTROL_CONFIG_INDEX]; 
mcu_can_cfg_callback_t mcu_can_cfg_callback;
volatile uint8_t mcu_cfg_ver_buf[SYS_CONFIG_VERSION_MAX_LEN];
mcu_protocol_control_status_e mcu_protocol_control_st;
mcu_can_flash_config_status_e mcu_can_flash_config_st;

static void mcu_hal_uart_init( void );
static void mcu_hal_uart_recv_cb(hal_uart_port_t uart_port, UINT8 *data, UINT16 len, void *arg);
static void mcu_devier_data_printf( mcu_uart_data_mode_e mode ,uint8_t * p_data , uint16_t d_len );
static void mcu_data_handle_task( void * pvParameters );
static void mcu_config_handle_task( void * pvParameters );

static void mcu_recv_data_queue_create(void);
static uint32_t mcu_recv_data_state_cb( uint8_t state );

static uint32_t mcu_recv_data_queue_get(mcu_recv_buf_typedef *mcu_msg , uint32_t time_out );
static uint32_t mcu_recv_data_processing( uint32_t time_out );

static uint32_t mcu_task_into_run_mode(void);
static uint32_t mcu_task_into_sleep_mode(void);
static uint32_t mcu_task_into_stop_mode(void);

static void mcu_can_cfg_sem_create(void);
static uint32_t mcu_can_cfg_sem_get( uint32_t timeout );
static void mcu_can_cfg_sem_put( uint32_t res );

/******************************************************************************/
static void mcu_can_cfg_data_queue_create(void);
static uint32_t mcu_can_cfg_data_queue_get( mcu_can_cfg_data_t *cfg , uint32_t time_out );
static uint32_t mcu_can_cfg_read_flash( void );
static uint32_t mcu_can_cfg_write_flash( uint8_t *data, uint16_t len );
static uint32_t mcu_can_cfg_write_index( uint8_t *exit, uint8_t index, uint8_t *data, uint16_t *len, uint8_t *st );
static uint32_t mcu_can_cfg_mod_task_create( mcu_can_cfg_para_t *para );
static uint32_t mcu_can_cfg_unit_index_handle_fun( mcu_can_cfg_type_e cfg_type, uint8_t index, uint8_t *data, uint16_t len , uint8_t state );
static uint32_t mcu_can_cfg_para_detection( void );

static void mcu_config_mod_task( void * pvParameters );

/** ****************************************************************************
* @remarks       static void  mcu_hal_uart_recv_cb(hal_uart_port_t uart_port, UINT8 *data, UINT16 len, void *arg)
* @brief         MCU UART数据回调函数
* @param[in]     无
* @param[out]    uart_port 串口号
* @param[out]    *data 串口数据的源地址
* @param[out]    len 串口数据长度
* @param[out]    *arg 系统参数
* @return        无
* @attention     无
*******************************************************************************/
static void  mcu_hal_uart_recv_cb(hal_uart_port_t uart_port, UINT8 *data, UINT16 len, void *arg)
{   
    mcu_recv_buf_typedef recv_buf;
    if( system_wakeup_queue_set( SYS_WAKEUP_TRIG_CAN ) == pdFAIL )/*当系统休眠后进行系统唤醒*/
    {
        if( power_man_task_state_get( mcu_power_man_id ) == TASK_SLEEP_MODE )
        {
            system_wakeup_event_queue_set( SYS_WAKEUP_TRIG_CAN );
        }
    }
    gaoz_mutex_lock( mcu_rev_data_mutex );
    if( len > UART_RX_BUF_SIZE )                                    /*内存边界判断*/
    {
        len = UART_RX_BUF_SIZE;
    }
    recv_buf.data = ( uint8_t *)gaoz_malloc_mem( len + 8 );       /*动态申请空间，空间位置处于FreeRtos总栈空间中*/
    if( recv_buf.data != NULL )
    {   
        memcpy( ( uint8_t *)recv_buf.data , ( uint8_t *)data ,len  );
        recv_buf.len = len;
        if( gaoz_queue_put( mcu_recv_data_queue, ( void * )&recv_buf , 10 ) < 0 )
        {
            gaoz_free_mem( (void *)recv_buf.data );
        }
    }
    gaoz_mutex_unlock( mcu_rev_data_mutex );
    
}

/** ****************************************************************************
* @remarks       static void mcu_hal_uart_init( void )
* @brief         MCU UART初始化函数
* @param[in]     无
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static void mcu_hal_uart_init( void )
{
    hal_uart_config_t drvcfg = {0};
    drvcfg.baud = 115200;
    drvcfg.parity = HAL_UART_NO_PARITY;    
    drvcfg.data_bits = HAL_UART_DATA_BITS_8;    
    drvcfg.stop_bits = HAL_UART_STOP_BITS_1;    
    drvcfg.rx_buf_size = UART_RX_BUF_SIZE;    
    drvcfg.tx_buf_size = UART_TX_BUF_SIZE;
    drvcfg.recv_timeout = 0; /*接收时间等待*/
    gaoz_hal_uart_init(MCU_UART_PORT, &drvcfg, mcu_hal_uart_recv_cb, NULL);
}

/** ****************************************************************************
* @remarks       void mcu_create_task( unsigned portBASE_TYPE uxPriority )
* @brief         创建MCU基层数据处理任务
* @param[in]     uxPriority 优先级
* @param[out]    无
* @return        无
* @attention     在系统启动后进行创建
*******************************************************************************/
void mcu_create_task( unsigned portBASE_TYPE uxPriority )
{
    /*创建任务互斥体*/
    mcu_uart_driver_mutex = gaoz_mutex_create();
    if( mcu_uart_driver_mutex == 0 )
    {
        while(1); /*创建失败*/
    }
    mcu_uart_driver_cb = NULL;
    mcu_uart_state_cb = NULL;
    /*创建任务互斥体*/
    mcu_rev_data_mutex = gaoz_mutex_create();
    if( mcu_rev_data_mutex == 0 )
    {
        while(1); /*创建失败*/
    }
    /***********************************************************/

    mcu_protocol_flash_open();            /*初始化MCU协议接口*/
    /***********************************************************/
    //mcu_hal_uart_init();                  /*初始化串口驱动*/
    mcu_recv_data_queue_create();
    /***********************************************************/
    mcu_can_cfg_mutex = gaoz_mutex_create();
    if( mcu_can_cfg_mutex == 0 )
    {
        while(1); /*创建失败*/
    }
    mcu_protocol_control_st = CONTROL_ST_INIT;
    mcu_can_cfg_callback = NULL;
    mcu_can_flash_config_st = CAN_CFG_FLASH_SAVE_NOT;
    memset((uint8_t *)mcu_cfg_ver_buf   , 0x00 , SYS_CONFIG_VERSION_MAX_LEN );  
    memset((uint8_t *)mcu_can_cfg_unit_para   , 0x00 , sizeof( mcu_can_cfg_para_t ) * UNIT_CONTROL_CONFIG_INDEX );  
    mcu_can_cfg_data_queue_create();      /*创建CAN 配置数据消息队列*/
    mcu_can_cfg_sem_create();
    can_config_par_list_init();
    /***********************************************************/
    gaoz_thread_create( mcu_data_handle_task, MCU_MAN_NAME, 1024*8, NULL, uxPriority );
#if( OS_MCU_CONFIG_ENABLED == 1 )    
    gaoz_thread_create( mcu_config_handle_task, MCU_CFG_NAME, 1024*8, NULL, uxPriority );
#endif
}

/** ****************************************************************************
* @remarks       static void mcu_recv_data_queue_create(void)
* @brief         创建发送数据消息队列
* @param[in]     无
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static void mcu_recv_data_queue_create(void)
{
    /* 创建模块网络发送数据的消息队列 */
    mcu_recv_data_queue = gaoz_queue_create( MCU_RECV_DATA_QUEUE_DEPTH, sizeof( mcu_recv_buf_typedef ) );
    if( mcu_recv_data_queue == 0 )
    {
        while( 1 ); /*创建失败,进行处理*/
    }
}

/** ****************************************************************************
* @remarks       static uint32_t mcu_recv_data_state_cb( void * state )
* @brief         MCU状态 ，回调函数
* @param[in]     *state 发送的数据不定类型
* @param[out]    无
* @return        pdPASS 发送数据成功  pdFAIL 发送数据失败
* @attention     无
*******************************************************************************/
static uint32_t mcu_recv_data_state_cb( uint8_t state )
{
	if( mcu_uart_state_cb == NULL )
    {
		return pdFAIL;
    }
	mcu_uart_state_cb( state );
	return pdPASS;
}

/** ****************************************************************************
* @remarks       uint32_t mcu_recv_data_queue_get(mcu_recv_buf_typedef *mcu_msg , uint32_t time_out )
* @brief         获取MCU数据发送消息队列数据
* @param[in]     *gnss_msg 获取的数据地址
* @param[out]    无
* @return        pdPASS 接收到数据 pdFAIL 未接收到数据
* @attention     必须在任务中运行
*******************************************************************************/
static uint32_t mcu_recv_data_queue_get(mcu_recv_buf_typedef *mcu_msg , uint32_t time_out )
{
    if( mcu_recv_data_queue == 0 )
    {
        mcu_recv_data_queue_create();
    }
    if( gaoz_queue_get( mcu_recv_data_queue, mcu_msg, time_out )  == 0 ) //等待回应信号量
    {
        return pdPASS;
    }
    else
    {
        return pdFAIL;
    }
    return pdFAIL;
}

/** ****************************************************************************
* @remarks       uint32_t mcu_uart_driver_open( mcu_uart_driver_callback_t recv_cb ,mcu_uart_state_callback_t state_cb )
* @brief         打开MCU 底层数据操作
* @param[in]     recv_cb 接收数据的回调函数 
* @param[out]    无
* @return        pdPASS 打开成功，pdFAIL打开失败
* @attention     无
*******************************************************************************/
uint32_t mcu_uart_driver_open( mcu_uart_driver_callback_t recv_cb ,mcu_uart_state_callback_t state_cb )
{
    uint32_t res = pdFAIL;
    uint32_t  osR = 0;
    if( mcu_uart_driver_mutex != 0 )
    {
        gaoz_mutex_lock( mcu_uart_driver_mutex );
        osR = 1;
    }
    
    if( mcu_uart_driver_cb == NULL )
    {
        mcu_hal_uart_init();
        mcu_uart_driver_cb = recv_cb;
        mcu_uart_state_cb = state_cb;
        res = pdPASS;
    }
    
    if(osR != 0)
    {
        gaoz_mutex_unlock( mcu_uart_driver_mutex );
    }
    
    return res;
}

/** ****************************************************************************
* @remarks       uint32_t mcu_uart_driver_send_data(uint8_t channel, uint8_t *pbuf , uint16_t dlen )
* @brief         MCU串口发送数据
* @param[in]     *pbuf 数据源地址
* @param[in]     dlen 数据长度
* @param[out]    无
* @return        pdPASS发送成功 ，  pdFAIL发送失败
* @attention     将发送的数据消息队列中，发送给任务进行数据发送。
*******************************************************************************/
uint32_t mcu_uart_driver_write( uint8_t *pbuf , uint16_t dlen )
{
    uint32_t  osR = 0;
    uint32_t  res = pdFAIL;

    if( pbuf == NULL ) 
    {
        return pdFAIL;
    }
    if( mcu_uart_driver_mutex != 0 )
    {
        gaoz_mutex_lock( mcu_uart_driver_mutex );
        osR = 1;
    }
    
    if( gaoz_hal_uart_put( MCU_UART_PORT, pbuf, dlen ) > 0 )
    {
        mcu_devier_data_printf( MCU_DATA_WRITE , pbuf, dlen );
        res = pdPASS;
    }
    
    if(osR != 0)
    {
        gaoz_mutex_unlock( mcu_uart_driver_mutex );
    }
    return (res);
}

/** ****************************************************************************
* @remarks       uint32_t mcu_uart_driver_close( void)
* @brief         MCU底层串口关闭
* @param[in]     无
* @param[out]    无
* @return        pdPASS关闭成功 ，  pdFAIL关闭失败
* @attention     
*******************************************************************************/
uint32_t mcu_uart_driver_close( void )
{
    uint32_t  osR = 0;
    uint32_t  res = pdFAIL;
    
    if( mcu_uart_driver_mutex != 0 )
    {
        gaoz_mutex_lock( mcu_uart_driver_mutex );
        osR = 1;
    }
    
    if( gaoz_hal_uart_deinit( MCU_UART_PORT ) == 0 )
    {
        res = pdPASS;
    }
    
    if(osR != 0)
    {
        gaoz_mutex_unlock( mcu_uart_driver_mutex );
    }
    
    return res;      
}

/** ****************************************************************************
* @remarks       static void mcu_devier_data_printf(uint8_t mode ,uint8_t * p_data , uint16_t d_len, uint8_t channel )
* @brief         MCU打印接收到的数
* @param[in]     * p_data打印数据源地址
* @param[in]     d_len 打印数据长度
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static void mcu_devier_data_printf( mcu_uart_data_mode_e mode ,uint8_t * p_data , uint16_t d_len )
{
    uint8_t *pBuf = NULL , i = 0;
    uint16_t data_len = 0 ,print = 0;
    /*动态申请空间，由于接收的数据需要转变为STRING类型，数据量是原始数据的2倍*/
    if( d_len > UART_RX_BUF_SIZE )
    {
        return;
    }
    pBuf = gaoz_malloc_mem( d_len * 2  + 50 );
    if( pBuf != NULL )
    {
        if( mode == MCU_DATA_WRITE )
        {
            data_len = sprintf((char *)pBuf,"MCU devier write data,%d,",d_len);
        }
        else
        {
            data_len = sprintf((char *)pBuf,"MCU devier read data,%d,",d_len);
        }
        data_len += HexToAsciiString((char *)&pBuf[data_len],( const char * )p_data, d_len);
        pBuf[ data_len ] = '\r';
        data_len++;
        pBuf[ data_len ] = '\n';
        data_len++;
        /*发送数据*/
        print = data_len / DEBUG_UART_TX_QUEUE_LEN;
        for( i = 0 ; i < print ; i ++ )
        {
            log_debug_send(DEBUG_MODE,MCU_MAN_NAME ,&pBuf[i*DEBUG_UART_TX_QUEUE_LEN],DEBUG_UART_TX_QUEUE_LEN);
        }
        print = data_len % DEBUG_UART_TX_QUEUE_LEN;
        if( print != 0 )
        {
            log_debug_send(DEBUG_MODE,MCU_MAN_NAME ,&pBuf[i*DEBUG_UART_TX_QUEUE_LEN],print);
        }
        gaoz_free_mem( (void *)pBuf );
    }
}

/** ****************************************************************************
* @remarks       static uint32_t mcu_task_into_run_mode(void)
* @brief         MCU任务进入运行状态
* @param[in]     无
* @param[out]    无
* @return        pdPASS 设置成功 pdFAIL 设置失败
* @attention     无
*******************************************************************************/
static uint32_t mcu_task_into_run_mode(void)
{
    task_modules_e state = TASK_MODE_INIT;
    uint32_t ret = pdFAIL;
    state = power_man_save_state_get( mcu_power_man_id ); /*获取任务的运行状态*/
    if( state != TASK_RUN_MODE )
    {   
        mcu_protocol_control_st = CONTROL_RUN_MCU_ST;
        mcu_protocol_control_run_status( CONTROL_RUN_MCU_ST );
        power_man_save_state_set( mcu_power_man_id ,TASK_RUN_MODE );
        log_debug_send(INFOR_MODE,MCU_MAN_NAME ,"<<<<<<<<<<*****MCU task enters RUN mode*****>>>>>>>>>>\r\n", 0);
        ret = pdPASS;
    }
    else if( state == TASK_RUN_MODE )
    {
        ret = pdPASS;
    }
    return ret;
}
/** ****************************************************************************
* @remarks       static uint32_t mcu_task_into_sleep_mode(void)
* @brief         MCU任务进入睡眠状态
* @param[in]     无
* @param[out]    无
* @return        pdPASS 设置成功 pdFAIL 设置失败
* @attention     无
*******************************************************************************/
static uint32_t mcu_task_into_sleep_mode(void)
{
    task_modules_e state = TASK_MODE_INIT;
    uint32_t ret = pdFAIL; 
    state = power_man_save_state_get( mcu_power_man_id ); /*获取任务的运行状态*/
    if( state != TASK_SLEEP_MODE )
    {   
        mcu_protocol_control_st = CONTROL_SLEEP_MCU_ST;
        mcu_protocol_control_run_status( CONTROL_SLEEP_MCU_ST );
        power_man_save_state_set( mcu_power_man_id ,TASK_SLEEP_MODE );
        log_debug_send(INFOR_MODE,MCU_MAN_NAME ,"<<<<<<<<<<*****MCU task enters SLEEP mode*****>>>>>>>>>>\r\n", 0);
        ret = pdPASS;
    }
    else if( state == TASK_SLEEP_MODE )
    {
        ret = pdPASS;
    }
    return ret;
}

/** ****************************************************************************
* @remarks       static uint32_t mcu_task_into_stop_mode(void)
* @brief         MCU任务进入停止状态
* @param[in]     无
* @param[out]    无
* @return        pdPASS 设置成功 pdFAIL 设置失败
* @attention     无
*******************************************************************************/
static uint32_t mcu_task_into_stop_mode(void)
{
    task_modules_e state = TASK_MODE_INIT;
    uint32_t ret = pdFAIL; 
    state = power_man_save_state_get( mcu_power_man_id ); /*获取任务的运行状态*/
    if( state != TASK_STOP_MODE )
    {   
        mcu_protocol_control_st = CONTROL_STOP_MCU_ST;
        mcu_protocol_control_run_status( CONTROL_STOP_MCU_ST );
        power_man_save_state_set( mcu_power_man_id ,TASK_STOP_MODE );
        log_debug_send(INFOR_MODE,MCU_MAN_NAME ,"<<<<<<<<<<*****MCU task enters STOP mode*****>>>>>>>>>>\r\n", 0);
        ret = pdPASS;
    }
    else if( state == TASK_STOP_MODE )
    {
        ret = pdPASS;
    }
    return ret;
}

/** ****************************************************************************
* @remarks       static uint32_t mcu_recv_data_processing( uint32_t time_out )
* @brief         MCU 接收数据处理任务
* @param[in]     * pvParameters 任务参数
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static uint32_t mcu_recv_data_processing( uint32_t time_out )
{
    uint32_t ret =pdFAIL;
    mcu_recv_buf_typedef mcu_recv_buf;
        
    if( mcu_recv_data_queue_get( &mcu_recv_buf ,time_out ) == pdPASS )   
    {
        //if( mcu_protocol_commad_parse( mcu_recv_buf.data, mcu_recv_buf.len ) != pdPASS )
        {
            if( mcu_uart_driver_cb != NULL )
            {
                mcu_uart_driver_cb( mcu_recv_buf.data ,mcu_recv_buf.len );
            }
        }
        
        mcu_devier_data_printf( MCU_DATA_READ , mcu_recv_buf.data ,mcu_recv_buf.len );
        gaoz_free_mem( (void *)mcu_recv_buf.data );
        ret = pdPASS;
    }
    
    return ret;
}

/** ****************************************************************************
* @remarks       static void mcu_data_handle_task( void * pvParameters )
* @brief         MCU 数据处理任务
* @param[in]     * pvParameters 任务参数
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static void mcu_data_handle_task( void * pvParameters )
{
    ( void ) pvParameters;
    task_modules_e mcu_run_st;
    volatile uint32_t mcu_sleep_time = 0;
    mon_reg_task_dog( 60 * GAOZ_TICK_PERIOD_S ,(uint8_t *)MCU_MAN_NAME , TASK_SEM_YES );  /*注册任务看门狗*/
    power_man_task_reg((uint8_t * )MCU_MAN_NAME,(uint8_t *)&mcu_power_man_id );             /*注册MCU电源管理*/
    log_debug_send(DEBUG_MODE,MCU_MAN_NAME ,"MCU data management task started successfully\r\n",0);
    for( ;; )
    {
        mon_reset_task_dog();
        mcu_run_st = power_man_task_state_get( mcu_power_man_id );                          /*获取任务运行的状态*/
        /*******************************MCU任务处于运行状态***********************************/
        if(  mcu_run_st == TASK_RUN_MODE )                                                  /*任务进入全速运行模式*/
        {   
			if( mcu_task_into_run_mode() != pdPASS )                                        /*判断睡眠是否设置成功，没有设置成功进入延时*/
			{
				gaoz_task_sleep(1000);
				continue;
			}
            mcu_sleep_time = 0;
            mcu_recv_data_state_cb( TASK_RUN_MODE );
            mcu_recv_data_processing( MCU_RECV_DATA_RUN_WAIT_TIME );
        }
        /*******************************MCU任务处于休眠状态************************************/
        else if(  mcu_run_st == TASK_SLEEP_MODE )                                           /*任务进入睡眠模式*/
        {
            if( mcu_recv_data_processing( MCU_RECV_DATA_SLEEP_WAIT_TIME ) != pdPASS )       /*获取MCU消息，阻塞5秒钟*/
            {
                mcu_sleep_time++;
                if( mcu_sleep_time >= POWER_MAN_TASK_INTO_SLEPP_TIME )
                {
                    mcu_sleep_time = POWER_MAN_TASK_INTO_SLEPP_TIME;
                    mcu_recv_data_state_cb( TASK_SLEEP_MODE );
                    mcu_task_into_sleep_mode();                                             /*判断任务任务是否进入睡眠模式，进入睡眠模式后进行长时间延时*/ 
                }
            }
            else
            {
                mcu_sleep_time = 0;
            }
        }
        /*******************************MCU任务处于停止状态************************************/
        else if(  mcu_run_st == TASK_STOP_MODE )                                            /*任务进入睡眠模式*/
        {
            mcu_recv_data_state_cb( TASK_STOP_MODE );
            if( mcu_task_into_stop_mode() ==  pdPASS )                                      /*判断任务任务是否进入停止模式，进入停止模式后进行长时间延时*/ 
            {
                gaoz_task_sleep( 1000 );
                continue;
            }
            gaoz_task_sleep( 1000 );
        }
        /*******************************MCU任务空循环状态************************************/
        else                                      
        {
            gaoz_task_sleep( 100 );
        }
    }
}


/******************************************************************************

 CAN CONFIG功能数据处理任务；
 本应该单独分开文件进行设计。但是心情有点烦躁所以就这么着吧，懒得弄了。
2021.08.02

******************************************************************************/

/** ****************************************************************************
* @remarks       static void mcu_can_cfg_sem_create(void)
* @brief         创建CAN CFG 信号量
* @param[in]     无
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static void mcu_can_cfg_sem_create(void)
{
    mcu_can_cfg_semaphore = gaoz_sem_new(0);
    if( mcu_can_cfg_semaphore == 0 )
    {
        while( 1 ); /*创建失败,进行处理*/
    }
    mcu_can_cfg_sem_reg = 0;
}

/** ****************************************************************************
* @remarks       static uint32_t mcu_can_cfg_sem_get( uint32_t *msg )
* @brief         获取CAN CFG 信号量数据
* @param[in]     timeout 阻塞时间
* @param[out]    无
* @return        pdPASS 成功 pdFAIL 失败
* @attention     必须在任务中运行
*******************************************************************************/
static uint32_t mcu_can_cfg_sem_get( uint32_t timeout )
{
    uint32_t res = 0;
    
    if( mcu_can_cfg_semaphore == 0 )
    {
        mcu_can_cfg_sem_create();
    }
    if( gaoz_sem_try_wait( mcu_can_cfg_semaphore , timeout ) == pdPASS )
    {
        res = mcu_can_cfg_sem_reg;
    }
    
    return res;
}

/** ****************************************************************************
* @remarks       static void mcu_can_cfg_sem_put( uint32_t res )
* @brief         发送CAN CFG 信号量数据
* @param[in]     res
* @param[out]    无
* @return        pdPASS 成功 pdFAIL 失败
* @attention     必须在任务中运行
*******************************************************************************/
static void mcu_can_cfg_sem_put( uint32_t res )
{    
    if( mcu_can_cfg_semaphore == 0 )
    {
        mcu_can_cfg_sem_create();
    }
    mcu_can_cfg_sem_reg = res;
    gaoz_sem_signal( mcu_can_cfg_semaphore );
}

/** ****************************************************************************
* @remarks       static void mcu_can_cfg_data_queue_create(void)
* @brief         创建CAN CONFIG 数据配置消息队列
* @param[in]     无
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static void mcu_can_cfg_data_queue_create(void)
{
    /* 创建模块网络发送数据的消息队列 */
    mcu_can_cfg_data_queue = gaoz_queue_create( MCU_CAN_CFG_DATA_QUEUE_DEPTH, sizeof( mcu_can_cfg_data_t ) );
    if( mcu_can_cfg_data_queue == 0 )
    {   
        while( 1 ); /*创建失败,进行处理*/
    }
}

/** ****************************************************************************
* @remarks       uint32_t mcu_can_cfg_data_queue_get(mcu_can_cfg_data_t *cfg , uint32_t time_out )
* @brief         获取CAN CFG数据接收消息队列数据
* @param[in]     *cfg 获取的数据地址，time_out阻塞时间
* @param[out]    无
* @return        pdPASS 接收到数据 pdFAIL 未接收到数据
* @attention     必须在任务中运行
*******************************************************************************/
static uint32_t mcu_can_cfg_data_queue_get( mcu_can_cfg_data_t *cfg , uint32_t time_out )
{
    if( mcu_can_cfg_data_queue == 0 )
    {
        mcu_can_cfg_data_queue_create();
    }
    if( gaoz_queue_get( mcu_can_cfg_data_queue, cfg, time_out )  == 0 ) //等待回应信号量
    {
        return pdPASS;
    }
    else
    {
        return pdFAIL;
    }
    
    return pdFAIL;
}

/** ****************************************************************************
* @remarks       uint32_t mcu_can_cfg_data_queue_put( mcu_can_cfg_data_t *cfg )
* @brief         获取CAN CFG数据发送消息队列数据
* @param[in]     *cfg 发送的数据地址
* @param[out]    无
* @return        pdPASS 成功    pdFAIL 失败
* @attention     必须在任务中运行
*******************************************************************************/
uint32_t mcu_can_cfg_data_queue_put( mcu_can_cfg_data_t *cfg )
{
    if( mcu_can_cfg_data_queue == 0 )
    {
        mcu_can_cfg_data_queue_create();
    }
    if( gaoz_queue_put( mcu_can_cfg_data_queue, cfg, MCU_CAN_CFG_DATA_SEND_TIME ) == 0 )
    {
        return pdPASS;
    }
    
    return pdFAIL;
}

/** ****************************************************************************
* @remarks       uint32_t mcu_can_cfg_write_flash( uint8_t *data, uint16_t len )
* @brief         将CAN cfg配置参数写入到FLASH中
* @param[in]     len 数据长度 ，*data 数据原地址
* @param[out]    无
* @return        pdPASS 成功 pdFAIL 失败
* @attention     必须在任务中运行
*******************************************************************************/
static uint32_t mcu_can_cfg_write_flash( uint8_t *data, uint16_t len )
{
    mcu_config_fault_infor_t error_code;
    
    error_code.faule = 0;
    if(( len > sizeof( sys_config_list_t ) ) || ( data == NULL ))
    {
        error_code.err = PORT_CFG_LEN_ERR;
        return error_code.faule;
    }
    sfb_block_reset( SF_CANCFG_DATA_ADDR, SF_CANCFG_DATA_FlAG_SECTORS );
    if( sfb_write_buf(   SF_CANCFG_DATA_ADDR, ( uint8_t* )data, len ) == pdPASS )
    {   
        error_code.faule = mcu_can_cfg_read_flash();
        if( error_code.faule == 0 )
        {
            log_debug_send(DEBUG_MODE,MCU_CFG_NAME ,"CAN configuration information is parsed successfully\r\n",0);
           
        }   
        else
        {
            log_debug_send(DEBUG_MODE,MCU_CFG_NAME ,"CAN configuration information is parsed failed\r\n",0);
  
        }
    }
    else
    {
        error_code.err = PORT_CFG_FLASH_ERR;
    }

    return error_code.faule;
}

/** ****************************************************************************
* @remarks       static uint32_t mcu_can_cfg_para_detection( void )
* @brief         MCU CAN 配置表任务状态检测
* @param[in]     无
* @param[out]    无
* @return        pdPASS 成功 pdFAIL 失败
* @attention     当CPU 重新下载配置参数或者进入休眠之前，需要将未接收的任务强制退出；
                 如何没有退出则会一直与MCU 进行数据交互CPU 则进入不了休眠；
*******************************************************************************/
static uint32_t mcu_can_cfg_para_detection( void )
{
    #define PARA_DETECTION_MAX_TIME ( 100 )   
    #define PARA_DETECTION_DELAY_MAX_TIME ( 100 )
    uint32_t ret = pdFAIL;
    uint8_t  i = 0 , num = 0 , dete = 0;
    
    for( i = 0 ; i < PARA_DETECTION_MAX_TIME ; i ++ )
    {
        for( dete = 0 ; dete < UNIT_CONTROL_CONFIG_INDEX ; dete ++ )
        {   /*检测任务创建的个数，当检测到任务创建成功后，发送强制退出命令*/
            if( mcu_can_cfg_unit_para[i].create == CFG_TASK_CREATE_SUCC )
            {
                mcu_can_cfg_unit_para[i].exit = CFG_TASK_EXIT_COMM;
                num++;
            }
        }
        if( num == 0 )
        {
            ret = pdPASS;
            break;
        }
        gaoz_task_sleep( PARA_DETECTION_DELAY_MAX_TIME );
    }
    memset((uint8_t *)mcu_can_cfg_unit_para   , 0x00 , sizeof( mcu_can_cfg_para_t ) * UNIT_CONTROL_CONFIG_INDEX );  
    return ret;
}
/** ****************************************************************************
* @remarks       uint32_t mcu_can_cfg_read_flash( void )
* @brief         从FLASH 空间内读取 CAN cfg配置参数
* @param[in]     无
* @param[out]    无
* @return        0 成功 ; >0失败
* @attention     必须在任务中运行
*******************************************************************************/
static uint32_t mcu_can_cfg_read_flash( void )
{   
    mcu_config_fault_infor_t error_code;
    uint8_t *rdata = NULL;
    uint8_t rlen = 0;
    sys_config_list_t *slist = NULL;
    
    error_code.faule = 0;
    rdata = ( uint8_t *)gaoz_malloc_mem( sizeof( sys_config_list_t ) );
    if( rdata == NULL )
    {
        error_code.err = PORT_CFG_UNKNOW_ERR;
        return error_code.faule;
    }
    memset((uint8_t *)rdata, 0x00, sizeof( sys_config_list_t ) );
    rlen = sizeof( sys_config_list_t ) - SYS_CONFIG_MAX_LEN;
    if( pdPASS ==  sfb_read_buf( SF_CANCFG_DATA_ADDR, (uint8_t* )rdata, rlen ) )
    {   
        slist = (sys_config_list_t *)rdata;
        slist->len = REV_U32( slist->len );
        slist->crc = REV_U32( slist->crc );  
        if( slist->len <= SYS_CONFIG_MAX_LEN )
        {
            if( pdPASS == sfb_read_buf( ( SF_CANCFG_DATA_ADDR +  rlen ) , (uint8_t* )slist->data, slist->len ))
            {   
                if( 1 )//slist->crc == calculate_crc32( CRC_INIT, (uint8_t *)slist->data , slist->len ) )
                {   /*CAN配置表映射信息初始化*/
                    mcu_devier_data_printf( MCU_DATA_READ ,(uint8_t * )slist->data , slist->len );
                    if( mcu_can_cfg_para_detection() == pdPASS )
                    {
                        can_config_par_list_init();
                        error_code.faule = can_config_index_map_init( (uint8_t *)slist->data , slist->len );
                        if( error_code.faule == 0 )
                        {
                            /*复制系统版本号*/
                            memcpy((uint8_t *)mcu_cfg_ver_buf,(uint8_t *)slist->version, SYS_CONFIG_VERSION_MAX_LEN );
                        }
                    }
                    else
                    {
                        error_code.err = PORT_CFG_TASK_ERR;
                    }
                }
                else
                {
                    error_code.err = MCU_CFG_CRC_ERR;
                }
            }
            else
            {
                error_code.err = PORT_CFG_FLASH_ERR;
            }
        }
        else
        {
            error_code.err = PORT_CFG_LEN_ERR;
        }
    }
    else
    {
        error_code.err = PORT_CFG_FLASH_ERR;
    }
    gaoz_free_mem(( void *  )rdata);
    
    return error_code.faule;
}

/** ****************************************************************************
* @remarks       uint32_t mcu_can_cfg_wf_handle( uint8_t *data, uint16_t len, uint32_t timeout )
* @brief         CAN CFG 参数 写入FLASH 操作接口
* @param[in]     *data 数据源地址，len 数据长度，timeout 阻塞时间，单位ms。0非阻塞。
* @param[out]    无
* @return        pdPASS 成功    pdFAIL 失败
* @attention     无
*******************************************************************************/
uint32_t mcu_can_cfg_wf_handle( uint8_t *data, uint16_t len, uint32_t timeout )
{
    uint32_t res = 0 , osr = 0;
    mcu_can_cfg_data_t cfg = { 0 };

    if( data == NULL )
    {
        return 0xFF;
    }
    if(( len == 0 ) || ( len > SYS_CONFIG_MAX_LEN ))
    {
        return 0xFF;
    }
    
    if( mcu_can_cfg_mutex != 0 )
    {
        gaoz_mutex_lock( mcu_can_cfg_mutex );
        osr = 1;
    }
    
    cfg.type = WRITE_PARA_FLASH;
    if( timeout != 0 )
    {
        cfg.block = MCU_CAN_CFG_BLOCK;
    }
    else
    {
        cfg.block = MCU_CAN_CFG_NONBLOCK;
    }
    cfg.len = len;
    cfg.data = data;
    if( mcu_can_cfg_data_queue_put( &cfg )    == pdPASS )
    {   
        if( timeout != 0 )
        {
            res = mcu_can_cfg_sem_get( timeout );
        }
        else
        {
            res = 0;
        }
    }
    
    if( osr != 0 )
    {
        gaoz_mutex_unlock( mcu_can_cfg_mutex );
    }
    
    return res;
}

/** ****************************************************************************
* @remarks       uint32_t mcu_can_cfg_dev_handle( uint32_t timeout )
* @brief         CAN CFG 参数 配置驱动
* @param[in]     timeout 阻塞时间，单位ms。0非阻塞。
* @param[out]    无
* @return        pdPASS 成功    pdFAIL 失败
* @attention     无
*******************************************************************************/
uint32_t mcu_can_cfg_dev_handle( uint32_t timeout )
{
    uint32_t res = pdFAIL , osr = 0;
    mcu_can_cfg_data_t cfg = { 0 };

    if( mcu_can_cfg_mutex != 0 )
    {
        gaoz_mutex_lock( mcu_can_cfg_mutex );
        osr = 1;
    }
    
    cfg.type = INIT_MCU_DRIVE;
    if( timeout != 0 )
    {
        cfg.block = MCU_CAN_CFG_BLOCK;
    }
    else
    {
        cfg.block = MCU_CAN_CFG_NONBLOCK;
    }
    if( mcu_can_cfg_data_queue_put( &cfg )    == pdPASS )
    {   
        if( timeout != 0 )
        {
            res = mcu_can_cfg_sem_get( timeout );
        }
        else
        {
            res = pdPASS;
        }
    }

    if( osr != 0 )
    {
        gaoz_mutex_unlock( mcu_can_cfg_mutex );
    }
    
    return res;
}

/** ****************************************************************************
* @remarks       uint32_t mcu_can_cfg_can_recv_handle( uint8_t *data, uint16_t len, uint16_t sn, uint16_t id, uint32_t timeout )
* @brief         CAN 数据接收处理
* @param[in]     *data 数据目标地址，*len 数据长度，sn 序列号，id ，timeout 阻塞时间，单位ms。0非阻塞。
* @param[out]    无
* @return        pdPASS 成功，pdFAIL 失败
* @attention     无
*******************************************************************************/
uint32_t mcu_can_cfg_can_recv_handle( uint8_t *data, uint16_t len, uint16_t sn, uint16_t id, uint32_t timeout )
{
    uint32_t res = pdFAIL, osr = 0;
    mcu_can_cfg_data_t cfg = { 0 };
    
    if( data == NULL )
    {
        return pdFAIL;
    }
    
    if( mcu_can_cfg_mutex != 0 )
    {
        gaoz_mutex_lock( mcu_can_cfg_mutex );
        osr = 1;
    }
    cfg.type = RECV_CAN_DATA;
    if( timeout != 0 )
    {
        cfg.block = MCU_CAN_CFG_BLOCK;
    }
    else
    {
        cfg.block = MCU_CAN_CFG_NONBLOCK;
    }
    cfg.len = len;
    cfg.sn = sn;
    cfg.id = id;
    cfg.data = data;
    if( mcu_can_cfg_data_queue_put( &cfg )    == pdPASS )
    {   
        if( timeout != 0 )
        {
            res = mcu_can_cfg_sem_get( timeout );
        }
        else
        {
            res = pdPASS;
        }
    }
    
    if( osr != 0 )
    {
        gaoz_mutex_unlock( mcu_can_cfg_mutex );
    }
    
    return res;
}

/** ****************************************************************************
* @remarks       uint32_t mcu_can_cfg_unit_index_handle( mcu_can_cfg_para_t *para, uint32_t timeout )
* @brief         CAN CFG  UNIT INDEX 数据获取
* @param[in]     index 节点，timeout 阻塞时间，单位ms。0非阻塞。
* @param[out]    *data 数据目标地址，*len数据长度目标地址，*state 数据状态目标地址
* @return        pdPASS 成功，pdFAIL 失败
* @attention    *len为0时表示没有任何数据。
                *state 数据类型分为3种，1 - 数据、2 - 状态、3 - 字符，当返回状态为pdFAIL时状态为0
                 timeout为0时表示为非阻塞，data、len、state 指针可以为NULL
                当state 数据类型为数据时，需要使用 bytes_to_double( uint8_t *bytes )函数进行转换，数据长度为8；
                当state数据类型为状态、字符时按住顺序进行读取
*******************************************************************************/
uint32_t mcu_can_cfg_unit_index_handle( uint8_t index,uint8_t *data,uint16_t *len,uint8_t *state, uint32_t timeout )
{
    uint32_t res = pdFAIL,osr = 0;
    mcu_can_cfg_data_t cfg = { 0 };
    mcu_can_cfg_para_t *para = NULL;
    
    if( index >= UNIT_CONTROL_CONFIG_INDEX )
    {
        return pdFAIL;
    }
    
    if( mcu_can_cfg_mutex != 0 )
    {
        gaoz_mutex_lock( mcu_can_cfg_mutex );
        osr = 1;
    }
    cfg.type = UNIT_INDEX_MSG;
    if( timeout != 0 )
    {
        cfg.block = MCU_CAN_CFG_BLOCK;
    }
    else
    {
        cfg.block = MCU_CAN_CFG_NONBLOCK;
    }
    para = ( mcu_can_cfg_para_t * )&mcu_can_cfg_unit_para[index];
    if(( para->create == CFG_TASK_CREATE_INIT ) && ( para->exit = CFG_TASK_EXIT_INIT ))
    {
        memset( (uint8_t *)para , 0x00 , sizeof( mcu_can_cfg_para_t ) );
        para->index = index;
        para->block = cfg.block;
        para->data = data; 
        para->len = len;
        para->state = state;
        cfg.len = sizeof( mcu_can_cfg_para_t );
        cfg.data = para;
        if( mcu_can_cfg_data_queue_put( &cfg )    == pdPASS )
        {
            /*等待创建任务成功*/
            if( timeout != 0 )
            {
                res = mcu_can_cfg_sem_get( timeout );
                para->block = MCU_CAN_CFG_NONBLOCK;
            }
            else
            {
                res = pdPASS;
            }
        }
    }
    if( osr != 0 )
    {
        gaoz_mutex_unlock( mcu_can_cfg_mutex );
    }
    
    return res;
}

/** ****************************************************************************
* @remarks       uint32_t mcu_can_cfg_dtc_index_handle( uint8_t index,uint8_t *data,uint16_t *len,uint8_t *state, uint32_t timeout )
* @brief         CAN CFG  DTC INDEX 数据获取
* @param[in]     index 节点，timeout 阻塞时间，单位ms。0非阻塞。
* @param[out]   *data 数据目标地址，*len数据长度目标地址，*state 数据状态目标地址
* @return        pdPASS 成功，pdFAIL 失败
* @attention    *len为0时表示没有任何数据。
                *state 数据类型分为3种，1 - 数据、2 - 状态、3 - 字符，当返回状态为pdFAIL时状态为0 （读数据状态）
                *state 数据类型分为2种 ，1-正确、0-错误 （写数据）
                 timeout为0时表示为非阻塞，data、len、state 指针可以为NULL
*******************************************************************************/
uint32_t mcu_can_cfg_dtc_index_handle( uint8_t index,uint8_t *data,uint16_t *len,uint8_t *state, uint32_t timeout )
{
    uint32_t ret = pdFAIL,osr = 0;
    mcu_can_cfg_data_t cfg = { 0 };
    mcu_can_cfg_para_t *para = NULL;
    
    if( index >= DTC_CONTROL_CONFIG_INDEX )
    {
        return pdFAIL;
    }
    
    if( mcu_can_cfg_mutex != 0 )
    {
        gaoz_mutex_lock( mcu_can_cfg_mutex );
        osr = 1;
    }
    cfg.type = DTC_INDEX_MSG;
    if( timeout != 0 )
    {
        cfg.block = MCU_CAN_CFG_BLOCK;
    }
    else
    {
        cfg.block = MCU_CAN_CFG_NONBLOCK;
    }
    
    para = ( mcu_can_cfg_para_t * )&mcu_can_cfg_dtc_para[index];
    if(( para->create == CFG_TASK_CREATE_INIT ) && ( para->exit = CFG_TASK_EXIT_INIT ))
    {
        memset( (uint8_t *)para , 0x00 , sizeof( mcu_can_cfg_para_t ) );
        para->index = index;
        para->block = cfg.block;
        para->data = data; 
        para->len = len;
        para->state = state;
        cfg.len = sizeof( mcu_can_cfg_para_t );
        cfg.data = para;
        if( mcu_can_cfg_data_queue_put( &cfg )    == pdPASS )
        {   /*等待创建任务成功*/
            if( timeout != 0 )
            {
                ret = mcu_can_cfg_sem_get( timeout );
            }
            else
            {
                ret = pdPASS;
            }
        }
    }
    
    if( osr != 0 )
    {
        gaoz_mutex_unlock( mcu_can_cfg_mutex );
    }
    
    return ret;
}

/** ****************************************************************************
* @remarks       uint32_t mcu_can_cfg_mod_task_create( mcu_can_cfg_para_t *para )
* @brief         创建 CAN 配置模块处理任务
* @param[in]     *para 节点参数，block 阻塞状态
* @param[out]    无
* @return        pdPASS 成功 pdFAIL 失败
* @attention     无
*******************************************************************************/
static uint32_t mcu_can_cfg_mod_task_create( mcu_can_cfg_para_t *para )
{
    uint32_t res = pdFAIL;
    char name[16] = { 0 };
    
    if( para->index >= UNIT_CONTROL_CONFIG_INDEX )
    {
        return pdFAIL;
    }
    if( can_config_index_format_num_get( para->index ) != 0 )
    {
        para->create = CFG_TASK_CREATE_SUCC;
        para->exit = CFG_TASK_EXIT_INIT;
        sprintf( (char *)name,"MCU_CFG_ID_%d",para->index );
        res = gaoz_thread_create( mcu_config_mod_task, name, 1024*2, (void *)para, OSI_PRIORITY_REALTIME );
        if( res == 0 )
        {
            res = pdPASS;
        }
    }
    if( res != pdPASS )
    {
        para->create = CFG_TASK_CREATE_INIT;
        para->exit = CFG_TASK_EXIT_INIT;
    }
    
    return res;
}

/** ****************************************************************************
* @remarks       void mcu_can_cfg_unit_index_handle_cb_set( mcu_can_cfg_callback_t  fun )
* @brief         设置UNIT INDEX 处理回调函数
* @param[in]     fun API 函数地址
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
void mcu_can_cfg_unit_index_handle_cb_set( mcu_can_cfg_callback_t  fun )
{
    if( mcu_can_cfg_callback == NULL )
    {
        mcu_can_cfg_callback = fun;
    }
}

/** ****************************************************************************
* @remarks       uint32_t mcu_can_cfg_unit_index_handle_fun( mcu_can_cfg_type_e cfg_type, uint8_t index, uint8_t *data, uint16_t len , uint8_t state )
* @brief         回调上层API函数
* @param[in]     cfg_type 数据状态，index 节点，*data 数据源地址，len 数据长度，state 数据状态
* @param[out]    无
* @return        pdPASS 成功 pdFAIL 失败
* @attention     无
*******************************************************************************/
static uint32_t mcu_can_cfg_unit_index_handle_fun( mcu_can_cfg_type_e cfg_type, uint8_t index, uint8_t *data, uint16_t len , uint8_t state )
{
    if( mcu_can_cfg_callback == NULL )
    {
        return pdFAIL;
    }
    mcu_can_cfg_callback( cfg_type,index,data,len,state );
    
    return pdPASS;
}

/** ****************************************************************************
* @remarks       uint32_t mcu_can_cfg_version_get( uint8_t *ver )
* @brief         获取MCU 配置表版本号
* @param[in]     *ver 读取版本号源地址
* @param[out]    无
* @return        pdPASS 成功 pdFAIL 失败
* @attention     ver 传入的地址长度大于SYS_CONFIG_VERSION_MAX_LEN
*******************************************************************************/
uint32_t mcu_can_cfg_version_get( uint8_t *ver )
{
    if( ver == NULL )
    {
        return pdFAIL;
    }
    memcpy((uint8_t *)ver,(uint8_t *)mcu_cfg_ver_buf, SYS_CONFIG_VERSION_MAX_LEN );
    
    return pdPASS;
}

/** ****************************************************************************
* @remarks       uint32_t mcu_can_mcu_version_get( uint8_t *version, uint32_t *len )
* @brief         获取MCU系统版本号
* @param[in]     无
* @param[out]    *version 版本号目标地址， *len 版本号长度
* @return        pdPASS成功/pdFAIL失败
* @attention     无
*******************************************************************************/
uint32_t mcu_can_mcu_version_get( uint8_t *version, uint32_t *len )
{
    return mcu_protocol_mcu_version_get( version, len );
}

/** ****************************************************************************
* @remarks       uint32_t mcu_can_mcu_port_control( mcu_can_port_control_status_e port_control, mcu_port_cfg_infor_t  port_cfg , uint16_t *out )
* @brief         MCU PORT 控制操作
* @param[in]     port_control 控制类型；port_cfg 端口配置
* @param[out]    *out 数据输出：
* @return        pdPASS成功/pdFAIL失败
* @attention     out 数据输出，为OUTPUT 时返回控制状态，INPUT 输入状态，ADC 数据
*******************************************************************************/
uint32_t mcu_can_mcu_port_control( mcu_can_port_control_status_e port_control, mcu_port_cfg_infor_t port_cfg , uint16_t *out )
{
    uint32_t ret = pdFAIL;
    
    if( port_control == PORT_CFG_INIT )
    {
        ret = mcu_protocol_mcu_port_cfg( port_cfg );
    }
    else if( port_control == PORT_CFG_READ )
    {
        ret = mcu_protocol_mcu_port_read_write( port_cfg , out );
    }
    else if( port_control == PORT_CFG_WRITE )
    {
        ret = mcu_protocol_mcu_port_read_write( port_cfg , out );
    }
    else
    {
        ret = pdFAIL;
    }

    return ret;
}

/** ****************************************************************************
* @remarks       static void mcu_config_handle_task( void * pvParameters )
* @brief         MCU 配置数据处理
* @param[in]     * pvParameters 任务参数
* @param[out]    无
* @return        无 
* @attention     无
*******************************************************************************/
static void mcu_config_handle_task( void * pvParameters )
{
    ( void ) pvParameters;
    volatile uint32_t result = 0;
    mcu_can_cfg_data_t can_cfg = { 0 };
    mon_reg_task_dog( 60 * GAOZ_TICK_PERIOD_S ,(uint8_t *)MCU_CFG_NAME , TASK_SEM_YES );  /*注册任务看门狗*/
    log_debug_send(DEBUG_MODE,MCU_CFG_NAME ,"MCU config handle task started successfully\r\n",0);
    if( mcu_can_cfg_read_flash() == 0 )
    {
        mcu_can_flash_config_st = CAN_CFG_FLASH_SAVE_OK;
        log_debug_send(DEBUG_MODE,MCU_CFG_NAME ,"CAN configuration information is parsed successfully\r\n",0);
    }
    for( ;; )
    {
        mon_reset_task_dog();
        if( mcu_can_cfg_data_queue_get( &can_cfg , MCU_CAN_CFG_DATA_WAIT_TIME ) == pdPASS )
        {
            /*1、写CAN 参数配置到FLASH，进行数据读取、数据映射表设置*/
            if( can_cfg.type == WRITE_PARA_FLASH )
            {
                result = mcu_can_cfg_write_flash( (uint8_t *)can_cfg.data, can_cfg.len );
                if( can_cfg.block == MCU_CAN_CFG_BLOCK )
                {
                    mcu_can_cfg_sem_put( result );
                }
                else //MCU_CAN_CFG_NONBLOCK
                {
                    mcu_can_cfg_unit_index_handle_fun( WRITE_PARA_FLASH,0x00,NULL,0x00,result );
                }
                if( result == 0 )
                {
                    mcu_can_cfg_dev_handle( 0 );    /*发送MCU终端参数配置*/
                }
            }
            /*2、读取CAN 、232、PORT底层驱动数据，进行设置。等待MCU应答*/
            else if( can_cfg.type == INIT_MCU_DRIVE )
            {
                /*CAN配置*********************************************/
                result = mcu_protocol_dev_init( CAN_INIT_DEV );  
                if( result == pdPASS )                              
                {
                    mcu_protocol_can_id_filtering_init();           /*数据过滤*/
                }
                if( can_cfg.block == MCU_CAN_CFG_BLOCK )
                {
                    mcu_can_cfg_sem_put( result );
                }
                else //MCU_CAN_CFG_NONBLOCK
                {
                    mcu_can_cfg_unit_index_handle_fun( INIT_MCU_DRIVE,CAN_INIT_DEV,NULL,0x00,result );
                }
                /*RS232配置*********************************************/
                result = mcu_protocol_dev_init( RS232_INIT_DEV );         
                mcu_can_cfg_unit_index_handle_fun( INIT_MCU_DRIVE,RS232_INIT_DEV,NULL,0x00,result );
                /*PORT配置*********************************************/
                result = mcu_protocol_dev_init( PORT_INIT_DEV ); /*初始PORT*/
                mcu_can_cfg_unit_index_handle_fun( INIT_MCU_DRIVE,PORT_INIT_DEV,NULL,0x00,result );
                
            }
            /*3、等待接受CAN RECV接受的数据，进行数据填充；应答MCU*/
            else if( can_cfg.type == RECV_CAN_DATA )
            {
                if( can_cfg.id == MCU_SEND_CAN_DATA )
                {
                    result = mcu_protocol_can_format_recv( (uint8_t *)can_cfg.data, can_cfg.len );
                    mcu_can_cfg_unit_index_handle_fun( RECV_CAN_DATA,CAN_RECV_DATA,(uint8_t *)can_cfg.data, can_cfg.len,result );
                    
                }
                else if( can_cfg.id == MCU_SEND_UART_DATA_REQ )
                {
                    result = mcu_protocol_can_format_recv( (uint8_t *)can_cfg.data, can_cfg.len );
                    mcu_can_cfg_unit_index_handle_fun( RECV_CAN_DATA,RS232_RECV_DATA,(uint8_t *)can_cfg.data, can_cfg.len,result );
                }
                else if( can_cfg.id == MCU_DRIVE_INIT_REQ )
                {
                    if( mcu_can_flash_config_st == CAN_CFG_FLASH_SAVE_OK )
                    {   
                        result = mcu_protocol_general_response_send( can_cfg.sn, can_cfg.id,  0 );   /*通用应答成功*/
                        mcu_can_cfg_unit_index_handle_fun( RECV_CAN_DATA,DEVICE_RECV_INIT, NULL, 0, result );
                        gaoz_task_sleep( MCU_CAN_CFG_DATA_SEND_TIME );                      /*等待100ms MCU状态稳定后发送CAN 配置表*/                                          
                        mcu_can_cfg_dev_handle( 0 );                                        /*发送参数表配置*/
                    }
                    else
                    {
                        result = mcu_protocol_general_response_send( can_cfg.sn, can_cfg.id,  1 );   /*通用应答失败*/
                        mcu_can_cfg_unit_index_handle_fun( RECV_CAN_DATA,DEVICE_RECV_INIT, NULL, 0,result );
                    }
                }
            }
            /*4、等待业务层发送的控制UNIT index，进行逻辑操作；返回参数 阻塞、非阻塞方式*/
            else if( can_cfg.type == UNIT_INDEX_MSG )
            {
                result = mcu_can_cfg_mod_task_create( (mcu_can_cfg_para_t *)can_cfg.data );
                if( result == pdFAIL )
                {
                    if( can_cfg.block == MCU_CAN_CFG_BLOCK )
                    {
                        mcu_can_cfg_sem_put( result );
                    }
                    else //MCU_CAN_CFG_NONBLOCK
                    {
                        mcu_can_cfg_unit_index_handle_fun( UNIT_INDEX_MSG,0x00,NULL,0x00,result );
                    }
                }
            }
            /*5、等待业务层发送的控制DTC index，进行逻辑操作；返回参数 阻塞、非阻塞方式*/
            else if( can_cfg.type == DTC_INDEX_MSG )
            {                         
                
            }
            /*6、循环检测主动发送的 UNIT 项目，进行数据处理；回调返回状态*/
            else
            {
                
            }
            if( can_cfg.data != NULL )
            {
                gaoz_free_mem( (void *)can_cfg.data );
            }
        }
    }
}


/** ****************************************************************************
* @remarks       uint32_t mcu_can_cfg_write_index( uint8_t index, uint8_t *data, uint16_t *len, uint8_t *st )
* @brief         写CAN 配置表信息 节点
* @param[in]     exit 强制退出的状态，index 参数节点
* @param[out]    *data发回参数的数据源地址，*len 返回参数的长度源地址，*st数据状态
* @return        pdPASS 成功 pdFAIL 失败
* @attention     无
*******************************************************************************/
static uint32_t mcu_can_cfg_write_index( uint8_t *exit, uint8_t index, uint8_t *data, uint16_t *len, uint8_t *st )
{
    uint32_t res = pdPASS;
    //unit_control_format_t format[UNIT_CONTROL_CONFIG_NUM];
    unit_control_infor_t control_infor = { 0 };
    can_recv_infor_t *can_recv = NULL;
    can_send_infor_t *can_send = NULL;
    port_input_infor_t *port_input = NULL;
    port_output_infor_t *port_output = NULL;
    uint8_t can_data[8] = { 0 }, cnt = 0, num = 0;
    uint16_t size = 0 , port_out = 0;
    
    if(( data == NULL ) || ( len == NULL ) || ( st == NULL ))
    {
        return pdFAIL;
    }
    *len = 0; /*将数据长度清0*/
    if( can_config_index_format_get( index ,&control_infor ) != pdPASS )
    {
        return pdFAIL;
    }
    if( control_infor.num > UNIT_CONTROL_CONFIG_NUM )
    {
        return pdFAIL;
    }
    for( cnt = 0 ; cnt < control_infor.cnt ; cnt ++ )
    {
        for( num = 0 ; num < control_infor.num ; num ++ )
        {
            /*检测消息格式的数据类型*/
            if( control_infor.format[num].type == UNIT_CONTROL_MOD_RECV_CAN )
            {
                can_recv = ( can_recv_infor_t * )control_infor.format[num].config;
                if( pdPASS != can_config_data_infor_get( can_recv->channel,can_recv->cid, index, num, ( uint8_t * )can_data ))
                {
                    res = pdFAIL;
                    break;
                }
                size += can_config_read_can_signal( (can_recv_infor_t *)can_recv, (    uint8_t * )st ,( uint8_t * )can_data, ( uint8_t * )&data[size] );
                if( size == 0 ) /*接收数据的长度*/
                {   
                    res = pdFAIL;
                    break;
                }
            }
            else if( control_infor.format[num].type == UNIT_CONTROL_MOD_RECV_PORT )
            {
                port_input = ( port_input_infor_t * )control_infor.format[num].config;
                if( pdPASS !=  mcu_protocol_port_signal_read( (port_input_infor_t *)port_input , (uint16_t *)&port_out ))
                {
                    res = pdFAIL;
                    break;
                }
                size += can_config_read_port_signal( (port_input_infor_t *)port_input,(    uint8_t * )st, port_out, ( uint8_t * )&data[size] );
                if( size == 0 ) /*接收数据的长度*/
                {
                    res = pdFAIL;
                    break;
                }
            }  
            else if( control_infor.format[num].type == UNIT_CONTROL_MOD_RECV_RS232 )
            {
                
            }
            else if( control_infor.format[num].type == UNIT_CONTROL_MOD_SEND_CAN )
            {
                can_send = ( can_send_infor_t * )control_infor.format[num].config;
                if( mcu_protocol_can_data_send( (can_send_infor_t *)can_send , exit ) != pdPASS )
                {
                    res = pdFAIL;
                    break;
                }
                else
                {
                    *st = 0x01;
                }
            }
            else if( control_infor.format[num].type == UNIT_CONTROL_MOD_SEND_PORT )
            {
                port_output = ( port_output_infor_t * )control_infor.format[num].config;
                if( mcu_protocol_port_signal_write( (port_output_infor_t *)port_output , exit ) != pdPASS )
                {
                    res = pdFAIL;
                    break;
                }
                else
                {
                    *st = 0x01;
                }
            }
            else if( control_infor.format[num].type == UNIT_CONTROL_MOD_SEND_RS232 )
            {
                
            }
            /*进行延时*/
            if( control_infor.format[num].time != 0 )
            {
                gaoz_task_sleep( control_infor.format[num].time );
            }
        }
        /*进行延时*/
        if( control_infor.period != 0 )
        {
            gaoz_task_sleep( control_infor.period );
        }
    }
    *len = size; /*赋值数据长度*/
    
    return res;
}

/** ****************************************************************************
* @remarks       static void mcu_config_mod_task( void * pvParameters )
* @brief         MCU 配置模块处理任务
* @param[in]     * pvParameters 任务参数
* @param[out]    无
* @return        无 
* @attention     无
*******************************************************************************/
static void mcu_config_mod_task( void * pvParameters )
{
    #define MCU_CONFIG_MOD_DATA_LEN ( 1024 )
    uint8_t  state = 0;
    uint8_t  *data = NULL;
    uint16_t dlen = 0;
    uint32_t result = 0;
    mcu_can_cfg_para_t *cfg_para = ( mcu_can_cfg_para_t * )pvParameters;
    
    if( cfg_para->create == CFG_TASK_CREATE_SUCC  )
    {
        log_debug_printf(DEBUG_MODE,MCU_CFG_NAME ,"MCU config module  task create successful,index=%d\r\n",cfg_para->index );
    }
    data = (uint8_t *)gaoz_fibo_malloc( MCU_CONFIG_MOD_DATA_LEN );
    if( data != NULL )
    {
        if( cfg_para->block == MCU_CAN_CFG_BLOCK )
        {
            result = mcu_can_cfg_write_index( (uint8_t *)&cfg_para->exit, cfg_para->index,  (uint8_t *)cfg_para->data, (uint16_t *)cfg_para->len, (uint8_t *)cfg_para->state );
            if( cfg_para->exit == CFG_TASK_EXIT_INIT )
            {
                mcu_can_cfg_sem_put( result );
            }
        }
        else //MCU_CAN_CFG_NONBLOCK
        {
            if(  pdPASS == mcu_can_cfg_write_index( (uint8_t *)&cfg_para->exit, cfg_para->index,  (uint8_t *)data, (uint16_t *)&dlen, (uint8_t *)&state ) )
            {
                mcu_can_cfg_unit_index_handle_fun( UNIT_INDEX_MSG,cfg_para->index,data,dlen,state );
            }
            else
            {
                if( cfg_para->exit == CFG_TASK_EXIT_INIT )
                {
                    mcu_can_cfg_unit_index_handle_fun( UNIT_INDEX_MSG,cfg_para->index,NULL,0,0 );
                }
            }
        }
    }
    gaoz_fibo_free( (void *)data );
    cfg_para->create = CFG_TASK_CREATE_INIT;
    if( cfg_para->exit == CFG_TASK_EXIT_COMM )
    {
        cfg_para->exit = CFG_TASK_EXIT_INIT;
        log_debug_printf(DEBUG_MODE,MCU_CFG_NAME ,"MCU config module  task (forced exited) successfully,index=%d\r\n",cfg_para->index);
    }
    else
    {
        log_debug_printf(DEBUG_MODE,MCU_CFG_NAME ,"MCU config module  task (aoto exited) successfully,index=%d\r\n",cfg_para->index);
    }
    gaoz_thread_delete();   /*任务删除*/
}



